package cn.ctyun.videoplayer.player;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.SurfaceTexture;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.FrameLayout;

import cn.ctyun.videoplayer.controller.BaseVideoController;
import cn.ctyun.videoplayer.controller.StandardVideoController;
import cn.ctyun.videoplayer.listener.OnVideoViewStateChangeListener;
import cn.ctyun.videoplayer.util.PlayerUtils;
import cn.ctyun.videoplayer.util.SDKLog;
import cn.ctyun.videoplayer.widget.ResizeSurfaceView;
import cn.ctyun.videoplayer.widget.ResizeTextureView;

import tv.danmaku.ijk.media.player.IjkMediaPlayer;

/**
 * 播放器
 * Created by Devlin_n on 2017/4/7.
 */

public class IjkVideoView extends BaseIjkVideoView {

    protected static final String TAG = IjkVideoView.class.getSimpleName();

    protected ResizeSurfaceView mSurfaceView;
    protected ResizeTextureView mTextureView;
    protected SurfaceTexture mSurfaceTexture;
    protected FrameLayout mPlayerContainer;
    protected boolean mIsFullScreen;//是否处于全屏状态
    //通过添加和移除这个view来实现隐藏和显示系统navigation bar，可以避免出现一些奇奇怪怪的问题
    protected View mHideNavBarView;

    public static final int SCREEN_SCALE_DEFAULT = 0;
    public static final int SCREEN_SCALE_16_9 = 1;
    public static final int SCREEN_SCALE_4_3 = 2;
    public static final int SCREEN_SCALE_MATCH_PARENT = 3;
    public static final int SCREEN_SCALE_ORIGINAL = 4;
    public static final int SCREEN_SCALE_CENTER_CROP = 5;

    protected int mCurrentScreenScale = SCREEN_SCALE_DEFAULT;

    protected int[] mVideoSize = {0, 0};

    private static final int FULLSCREEN_FLAGS = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;


    public IjkVideoView(@NonNull Context context) {
        this(context, null);
    }

    public IjkVideoView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public IjkVideoView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView();
    }

    /**
     * 初始化播放器视图
     */
    protected void initView() {
        mPlayerContainer = new FrameLayout(getContext());
        mPlayerContainer.setBackgroundColor(Color.BLACK);
        LayoutParams params = new LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);
        this.addView(mPlayerContainer, params);

        mHideNavBarView = new View(getContext());
        mHideNavBarView.setSystemUiVisibility(FULLSCREEN_FLAGS);
    }

    /**
     * 创建播放器实例，设置播放地址及播放器参数
     */
    @Override
    protected void initPlayer() {
        super.initPlayer();
        addDisplay();
    }

    protected void addDisplay() {
        if (mPlayerConfig.usingSurfaceView) {
            addSurfaceView();
        } else {
            addTextureView();
        }
    }

    /**
     * 向Controller设置播放状态，用于控制Controller的ui展示
     */
    @Override
    protected void setPlayState(int playState) {
        SDKLog.info(TAG, "setPlayState, state=" + playState);
        mCurrentPlayState = playState;
        if (mVideoController != null)
            mVideoController.setPlayState(playState);
        if (mOnVideoViewStateChangeListeners != null) {
            for (OnVideoViewStateChangeListener listener : mOnVideoViewStateChangeListeners) {
                listener.onPlayStateChanged(playState);
            }
        }
    }

    /**
     * 向Controller设置播放器状态，包含全屏状态和非全屏状态
     */
    @Override
    protected void setPlayerState(int playerState) {
        mCurrentPlayerState = playerState;
        if (mVideoController != null)
            mVideoController.setPlayerState(playerState);
        if (mOnVideoViewStateChangeListeners != null) {
            for (OnVideoViewStateChangeListener listener : mOnVideoViewStateChangeListeners) {
                listener.onPlayerStateChanged(playerState);
            }
        }
    }

    @Override
    protected void startPlay() {
        SDKLog.info(TAG, "startPlay, url=" + mCurrentUrl);
        if (mPlayerConfig.addToPlayerManager) {
            VideoViewManager.instance().releaseVideoPlayer();
            VideoViewManager.instance().setCurrentVideoPlayer(this);
        }
        super.startPlay();
    }

    /**
     * 添加SurfaceView
     */
    private void addSurfaceView() {
        mPlayerContainer.removeView(mSurfaceView);
        mSurfaceView = new ResizeSurfaceView(getContext());
        SurfaceHolder surfaceHolder = mSurfaceView.getHolder();
        surfaceHolder.addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                if (mMediaPlayer != null) {
                    mMediaPlayer.setDisplay(holder);
                }
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
            }
        });
        surfaceHolder.setFormat(PixelFormat.RGBA_8888);
        LayoutParams params = new LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT,
                Gravity.CENTER);
        mPlayerContainer.addView(mSurfaceView, 0, params);
    }

    /**
     * 添加TextureView
     */
    private void addTextureView() {
        mPlayerContainer.removeView(mTextureView);
        mSurfaceTexture = null;
        mTextureView = new ResizeTextureView(getContext());
        mTextureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
            @Override
            public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
                if (mSurfaceTexture != null) {
                    mTextureView.setSurfaceTexture(mSurfaceTexture);
                } else {
                    mSurfaceTexture = surfaceTexture;
                    mMediaPlayer.setSurface(new Surface(surfaceTexture));
                }
            }

            @Override
            public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, int height) {
            }

            @Override
            public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
                return mSurfaceTexture == null;
            }

            @Override
            public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
            }
        });
        LayoutParams params = new LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT,
                Gravity.CENTER);
        mPlayerContainer.addView(mTextureView, 0, params);
    }

    protected boolean checkNetwork() {
        if (PlayerUtils.getNetworkType(getContext()) == PlayerUtils.NETWORK_MOBILE
                && !IS_PLAY_ON_MOBILE_NETWORK) {
            if (mVideoController != null) {
                mVideoController.showStatusView();
            }
            return true;
        }
        return false;
    }

    @Override
    public void release() {
        super.release();
        mPlayerContainer.removeView(mTextureView);
        mPlayerContainer.removeView(mSurfaceView);
        if (mSurfaceTexture != null) {
            mSurfaceTexture.release();
            mSurfaceTexture = null;
        }
        mCurrentScreenScale = SCREEN_SCALE_DEFAULT;
//        mPlayerContainer.removeView(mVideoController);
    }

    /**
     * 进入全屏
     */
    @Override
    public void startFullScreen() {
        if (mVideoController == null) return;
        Activity activity = PlayerUtils.scanForActivity(mVideoController.getContext());
        if (activity == null) return;
        if (mIsFullScreen) return;
        PlayerUtils.hideActionBar(mVideoController.getContext());
        this.addView(mHideNavBarView);
        activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        this.removeView(mPlayerContainer);
        ViewGroup contentView = activity
                .findViewById(android.R.id.content);
        LayoutParams params = new LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);
        contentView.addView(mPlayerContainer, params);
        mOrientationEventListener.enable();
        mIsFullScreen = true;
        setPlayerState(PLAYER_FULL_SCREEN);

        if (mOnEnterFullScreenListener != null) {
            mOnEnterFullScreenListener.enterFullScreen();
        }
    }

    /**
     * 退出全屏
     */
    @Override
    public void stopFullScreen() {
        if (mVideoController == null) return;
        Activity activity = PlayerUtils.scanForActivity(mVideoController.getContext());
        if (activity == null) return;
        if (!mIsFullScreen) return;
        if (!mPlayerConfig.mAutoRotate) mOrientationEventListener.disable();
        PlayerUtils.showActionBar(mVideoController.getContext());
        this.removeView(mHideNavBarView);
        activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        ViewGroup contentView = activity
                .findViewById(android.R.id.content);
        contentView.removeView(mPlayerContainer);
        LayoutParams params = new LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);
        this.addView(mPlayerContainer, params);
        this.requestFocus();
        mIsFullScreen = false;
        setPlayerState(PLAYER_NORMAL);

        if (mOnExitFullScreenListener != null) {
            mOnExitFullScreenListener.exitFullScreen();
        }
    }

    /**
     * 判断是否处于全屏状态
     */
    @Override
    public boolean isFullScreen() {
        return mIsFullScreen;
    }

    /**
     * 重试
     */
    @Override
    public void retry() {
        super.retry();
        addDisplay();
        startPrepare(true);
    }

    @Override
    public void onInfo(int what, int extra) {
        super.onInfo(what, extra);
        switch (what) {
            case IjkMediaPlayer.MEDIA_INFO_VIDEO_ROTATION_CHANGED:
                if (mTextureView != null)
                    mTextureView.setRotation(extra);
                break;
        }
    }

    @Override
    public void onVideoSizeChanged(int videoWidth, int videoHeight) {
        mVideoSize[0] = videoWidth;
        mVideoSize[1] = videoHeight;
        if (mPlayerConfig.usingSurfaceView) {
            mSurfaceView.setScreenScale(mCurrentScreenScale);
            mSurfaceView.setVideoSize(videoWidth, videoHeight);
        } else {
            mTextureView.setScreenScale(mCurrentScreenScale);
            mTextureView.setVideoSize(videoWidth, videoHeight);
        }
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus) {
            //重新获得焦点时保持全屏状态
            mHideNavBarView.setSystemUiVisibility(FULLSCREEN_FLAGS);
        }

        if (isInPlaybackState() && (mPlayerConfig.mAutoRotate || mIsFullScreen)) {
            if (hasFocus) {
                postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mOrientationEventListener.enable();
                    }
                }, 800);
            } else {
                mOrientationEventListener.disable();
            }
        }
    }


    /**
     * 设置控制器
     */
    public void setVideoController(@Nullable BaseVideoController mediaController) {
        mPlayerContainer.removeView(mVideoController);
        mVideoController = mediaController;
        if (mediaController != null) {
            mediaController.setMediaPlayer(this);
            LayoutParams params = new LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT);
            mPlayerContainer.addView(mVideoController, params);

            notifyVideoControllerChange();
        }
    }

    public StandardVideoController getVideoController() {
        return (StandardVideoController) mVideoController;
    }

    protected void notifyVideoControllerChange() {}

    /**
     * 改变返回键逻辑，用于activity
     */
    public boolean onBackPressed() {
        return mVideoController != null && mVideoController.onBackPressed();
    }

    /**
     * 设置视频比例
     */
    @Override
    public void setScreenScale(int screenScale) {
        this.mCurrentScreenScale = screenScale;
        if (mSurfaceView != null) {
            mSurfaceView.setScreenScale(screenScale);
        } else if (mTextureView != null) {
            mTextureView.setScreenScale(screenScale);
        }
    }

    /**
     * 设置镜像旋转，暂不支持SurfaceView
     */
    @Override
    public void setMirrorRotation(boolean enable) {
        if (mTextureView != null) {
            mTextureView.setScaleX(enable ? -1 : 1);
        }
    }

    /**
     * 截图，暂不支持SurfaceView
     */
    @Override
    public Bitmap doScreenShot() {
        if (mTextureView != null) {
            return mTextureView.getBitmap();
        }
        return null;
    }

    /**
     * 获取视频宽高,其中width: mVideoSize[0], height: mVideoSize[1]
     */
    @Override
    public int[] getVideoSize() {
        return mVideoSize;
    }

    /**
     * 旋转视频画面
     *
     * @param rotation 角度
     */
    @Override
    public void setRotation(float rotation) {
        if (mTextureView != null) {
            mTextureView.setRotation(rotation);
            mTextureView.requestLayout();
        }

        if (mSurfaceView != null) {
            mSurfaceView.setRotation(rotation);
            mSurfaceView.requestLayout();
        }
    }

    //------------------------

    @Override
    public void hidePausedAd() {
        mVideoController.hidePausedAd();
    }

//    /**
//     * 设置播放器播放的url
//     * @param url
//     */
//    public void setUrl(String url) {
//
//    }

//    /**
//     * 设置一个片头广告URL，在调用视频`player.play()`方法之后，会先播放广告之后在播放正片。
//     * @param url
//     */
//    public void setStartAd(String url) {
//
//    }
//
//    /**
//     * 设置一个片尾广告，在播放视频之后播放。
//     * @param url
//     */
//    public void setEndAd(String url) {
//
//    }

//    /**
//     * 设置播放器在未播放时显示的图片，url是图片的地址
//     * @param thumbUrl
//     */
//    public void setPoster(String thumbUrl) {
//        setThumb(thumbUrl);
//    }
//
//    /**
//     * 设置播放器播放的视频id，这个 id 是 xstore 点播提供的视频id，这个 id 可以在界面 xstore 提供的 api 中取得。
//     * 播放器需要通过这个 id 通过一个 restful 接口来取得视频以及Poster的 url
//     * @param id
//     */
//    public void setVideoId(String id) {
//
//    }
//
//    /**
//     * 设置视频允许播放的时长，单位为秒。请加载视频以及播放时以此为节点。
//     * @param sec
//     */
//    public void setPlayableVideoDuration(long sec) {
//
//    }
//
//    /**
//     * 显示评论输入框，应包含输入框和发送按钮。这个输入框的内容可以通过事件 `player.onCommentTextSent()` 的事件中获取
//     * @param show
//     */
//    public void showCommentInput(boolean show) {
//
//    }
//
//    /**
//     * 传入一张图片 URL，在视频暂停时在播放器中间显示。
//     * @param url
//     */
//    public void setPausedAd(String url) {
//
//    }
//
//    /**
//     * 设置 url 完成之后，在未播放之前，调用此方法可以预加载视频
//     */
//    public void load() {
//
//    }
//
////    /**
////     * 播放视频，如果有广告则先播放广告
////     */
////    public void play() {
////
////    }
//
//    /**
//     * 播放视频，如果视频没有调用 load() 方法加载，则先加载视频再播放，ignoreStartAd == true时 会跳过片头广告直接播放视频
//     */
//    public void play(boolean ignoreAd) {
//
//    }
//
//    /**
//     * 暂停视频
//     */
//    public void pause() {
//
//    }
//
////    /**
////     * 停止视频的播放，将 seek 指针指向最后。
////     */
////    public void stop() {
////
////    }
//
//    /**
//     * 设置快进/快退的时间点，msec 是微秒，如传入的参数小于0，退到 0s，如果大于视频的总时长，到最后，返回值返回实际到达的毫秒数。
//     */
//    public void seekTo(long msec) {
//
//    }
//
//    /**
//     * 返回视频的时长
//     * @return
//     */
//    public long getDuration() {
//        return 0;
//    }
//
//    /**
//     * 返回当前视频播放的位置，时间单位为毫秒
//     * @return
//     */
//    public long getCurrentPosition() {
//        return 0;
//    }
//
//    /**
//     * 返回当前视频预加载缓存的时间范围
//     * @return
//     */
//    public String getBufferedRange() {
//        return "{\"from\": long, \"to\": long}";
//    }
//
//    /**
//     * 返回当前视频预加载的时间的结束时间点
//     * @return
//     */
//    public long getBufferedEnd() {
//        return 0;
//    }
//
//    /**
//     * 返回加载的百分比，该值应该大于0，小于1，精确到小数点后 2 位
//     * @return
//     */
////    public float getBufferedPercentage() {
////        return 0f;
////    }
//
//    /**
//     * 设置音量 该值应该大于0，小于1，精确到小数点后 2 位
//     * @param volume
//     */
//    public void setVolume(float volume) {
//
//    }
//
//    /**
//     * 设置静音。同时记录当前音量，当使用 resumeVolume 时设置回静音前音量。
//     */
//    public void mute() {
//
//    }
//
//    /**
//     * 从静音状态返回
//     */
//    public void resumeVolume() {
//
//    }
//
//    /**
//     * 返回当前视频是否静音
//     * @return
//     */
//    public boolean isMuted() {
//        return false;
//    }
//
//    /**
//     * 设置全屏播放
//     */
//    public void enterFullScreen() {
//
//    }
//
//    /**
//     * 退出全屏播放
//     */
//    public void existFullScreen() {
//
//    }
//
//    /**
//     * 设置播放速度
//     * @param speed
//     */
//    public void setScrollSpeed(float speed) {
//
//    }
//
//    /**
//     * 设置弹幕，弹幕为一个对象，包含了各所有弹幕列表，每一条弹幕应该包含弹幕的内容、弹幕出现的时间点以及弹幕的格式。具体弹幕的对象类似：
//     *
//     * ```json
//     * {
//     *         "text": "弹幕内容",
//     *         "style": {
//     *             "color": "auto",
//     *             "fontSize": "auto",
//     *             "opacity": 1
//     *         },
//     *         "speed": 1
//     *     }
//     * ```
//     * @param floatingTextArray
//     */
//    public void setFloatingComments(String floatingTextArray) {
//
//    }
//
//    /**
//     * 将列表中的弹幕增加到当前弹幕列表中进行展示。
//     * @param floatingTextArray
//     */
//    public void addFloatingComments(String floatingTextArray) {
//
//    }
//
//    /**
//     * 立刻停止播放片头广告
//     */
//    public void stopStartAd() {
//
//    }
//
//    /**
//     * 立刻停止播放片尾广告
//     */
//    public void stopEndAd() {
//
//    }
//
//    /**
//     * 隐藏正在显示的暂停广告费
//     */
//    public void hidePausedAd() {
//
//    }

}
